/**
 * 1. webpack 加载 webpack.config.js 文件，然后 new TestPlugin()，执行插件的 constructor
 * 2. webpack 创建 compiler 对象
 * 3. 遍历所有的 plugin 中插件的对象，调用插件对象中的 apply 方法
 * 4. 执行剩下编译流程（触发各个 hook 事件）
 */
module.exports = class TestPlugin {
    constructor() {
        console.log('TestPluguin constructor');
    }

    apply(compiler) {
        console.log("TestPlugin apply")

        // *同步钩子*, 只能用tap注册
        compiler.hooks.compile.tap("TestPlugin", (compilationParams) => {
            console.log("compiler.compile()")
        })

        /**
         * *异步并行钩子*，定义的异步钩子会并行执行，不会相互等待
         * tapAsync 回调函数传参为 compilation 对象和 callback 函数
         */
        compiler.hooks.make.tapAsync("TestPlugin", (compilation, callback) => {
            console.log('------------')
            setTimeout(() => {
                console.log("compiler.make() async")
                callback()
            }, 1000)
        })

        // tapPromise 回调函数传参为 compilation 对象，返回值接受一个 Promise 对象，当 Promise 对象状态为 resolved 时，该钩子执行结束
        compiler.hooks.make.tapPromise("TestPlugin", (compilation) => {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log('compiler.make() promise')
                    resolve()
                }, 1500)
            })
        })

        /**
         * *异步串行钩子* 定义的异步钩子会按照定义的顺序，串行执行（等待上一个异步钩子函数执行完成之后才执行下一个）
         *  如果定义同步钩子，则不会等待该同步钩子里的异步代码执行完毕就开始执行下一个钩子函数了
         */
        compiler.hooks.emit.tap("TestPlugin", (compilation) => {
            console.log('------------')
            setTimeout(() => {
                console.log("compiler.emit() sync")
            }, 1000)
        })

        compiler.hooks.emit.tapAsync("TestPlugin", (compilation, callback) => {
            setTimeout(() => {
                console.log("compiler.emit() async")
                callback()
            }, 1000)
        })

        compiler.hooks.emit.tapPromise("TestPlugin", (compilation) => {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log("compiler.emit() Promise")
                    resolve()
                }, 1000)
            }
            )
        })
    }
}